<?php

namespace App\Exceptions;

use App\Exceptions\ValidationException as MyValidationException;
use App\Models\ExceptionError;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Validation\ValidationException;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Throwable;
use Tymon\JWTAuth\Exceptions\JWTException;

class Handler extends ExceptionHandler
{
    public $logId;

    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [
        AuthorizationException::class,
        HttpException::class,
        ModelNotFoundException::class,
        ValidationException::class,
        MyValidationException::class,
    ];

    /**
     * @return mixed
     */
    public function getLogId()
    {
        return $this->logId;
    }

    /**
     * @param mixed $logId
     */
    public function setLogId($logId): void
    {
        $this->logId = $logId;
    }

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param \Throwable $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Throwable $exception)
    {
        if (!$this->shouldntReport($exception)) {
            // 记录日志 和 消息通知（邮件短信等）
            $this->exceptionError($exception);
        }
        parent::report($exception);
    }

    protected function exceptionError(Throwable $exception)
    {

        try {
            $log = ExceptionError::query()->create([
                'message'         => $exception->getMessage(),
                'code'            => $exception->getCode(),
                'file'            => $exception->getFile(),
                'line'            => $exception->getLine(),
                'trace'           => $exception->getTrace(),
                'trace_as_string' => $exception->getTraceAsString(),
            ]);
            $this->setLogId($log->getId());

        } catch (Exception $e) {
            // Log::error($e);
        }
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Throwable $exception
     * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $exception)
    {
        if ($exception instanceof JWTException) {
            $message = $exception->getMessage();
        } elseif ($exception instanceof \App\Exceptions\ValidationException) {
            $message = $exception->getMessage();
        } elseif ($exception instanceof \App\Exceptions\SystemException) {
            $message = $exception->getMessage();
        } else {
            // 定义异常开关
            if (config('app.debug')) {
                return parent::render($request, $exception);
            }
            $message = '服务器内部错误';
        }

        return response()->json(response_error_msg($message), 500);
    }
}
